#include "config.hpp"
#include <fstream>
#include <iostream>
#include <string>
#include <algorithm>

/**
 * 辅助函数：去除字符串首尾的空白字符
 * 
 * @param s 需要处理的字符串
 * @return 去除首尾空白后的字符串
 * 
 * 该函数移除字符串开头和结尾的空格、制表符、换行符和回车符
 * 如果字符串全部由空白字符组成，则返回原字符串
 */
static std::string trim(const std::string& s) {
    // 查找第一个非空白字符的位置
    size_t first = s.find_first_not_of(" \t\n\r");
    if (std::string::npos == first) {
        // 如果没有找到非空白字符（字符串全是空白），返回原字符串
        return s;
    }
    // 查找最后一个非空白字符的位置
    size_t last = s.find_last_not_of(" \t\n\r");
    // 提取从第一个非空白字符到最后一个非空白字符的子串
    return s.substr(first, (last - first + 1));
}

/**
 * 从配置文件加载应用程序参数
 * 
 * @param filename 配置文件路径
 * @param config 用于存储加载参数的AppConfig对象引用
 * @return 加载成功返回true，失败返回false
 * 
 * 该函数解析简单的键值对格式的配置文件，格式为：
 * key=value
 * 
 * 支持的特性：
 * - 忽略空行
 * - 忽略以#开头的注释行
 * - 忽略以[开头的节标题行（INI格式兼容）
 * - 键值对之间使用=分隔
 * - 自动去除键和值两端的空白字符
 */
bool loadConfig(const std::string& filename, AppConfig& config) {
    // 尝试打开配置文件
    std::ifstream file(filename);
    if (!file.is_open()) {
        std::cerr << "警告: 无法打开配置文件 '" << filename << "'。将使用默认配置。" << std::endl;
        return false;
    }

    // 逐行读取配置文件
    std::string line;
    while (std::getline(file, line)) {
        // 预处理：去除首尾空白
        line = trim(line);
        
        // 忽略空行、注释行和节标题行
        if (line.empty() || line[0] == '#' || line[0] == '[') {
            continue;
        }

        // 查找键值分隔符
        size_t delimiter_pos = line.find('=');
        if (delimiter_pos != std::string::npos) {
            // 提取键和值，并去除两端空白
            std::string key = trim(line.substr(0, delimiter_pos));
            std::string value = trim(line.substr(delimiter_pos + 1));

            // 根据键名设置相应的配置参数
            // 相机设置
            if (key == "index") {
                try {
                    config.camera_index = std::stoi(value);
                } catch (const std::exception& e) {
                    std::cerr << "警告: 配置文件中 camera index 值无效: " << value << std::endl;
                    // 保持默认值不变
                }
            } else if (key == "resolution_preset") {
                // 去除可能存在的引号
                value.erase(std::remove(value.begin(), value.end(), '\"'), value.end());
                config.resolution_preset = value;
            } else if (key == "display_scale_factor") {
                try { config.display_scale_factor = std::stod(value); } catch (...) {}
            } else if (key == "title") {
                config.window_title = value;
            }
            // 显示选项
            else if (key == "show_binary") {
                // 将字符串 "true" (不区分大小写) 转为布尔值
                std::transform(value.begin(), value.end(), value.begin(), ::tolower);
                config.show_binary = (value == "true");
            } 
            // 图像处理参数
            else if (key == "use_adaptive_threshold") {
                std::transform(value.begin(), value.end(), value.begin(), ::tolower);
                config.use_adaptive_threshold = (value == "true");
            } else if (key == "use_gaussian_blur") {
                std::transform(value.begin(), value.end(), value.begin(), ::tolower);
                config.use_gaussian_blur = (value == "true");
            } else if (key == "gaussian_kernel_size") {
                try { 
                    config.gaussian_kernel_size = std::stoi(value); 
                } catch (...) {
                    // 静默处理转换异常，保持默认值
                }
            } else if (key == "threshold_value") {
                try { 
                    config.threshold_value = std::stoi(value); 
                } catch (...) {
                    // 静默处理转换异常，保持默认值
                }
            } else if (key == "adaptive_block_size") {
                try { 
                    config.adaptive_block_size = std::stoi(value); 
                } catch (...) {
                    // 静默处理转换异常，保持默认值
                }
            } else if (key == "adaptive_c") {
                try { 
                    config.adaptive_c = std::stod(value); 
                } catch (...) {
                    // 静默处理转换异常，保持默认值
                }
            } 
            // 轮廓和形状检测参数
            else if (key == "min_contour_area") {
                try { 
                    config.min_contour_area = std::stod(value); 
                } catch (...) {
                    // 静默处理转换异常，保持默认值
                }
            } else if (key == "shape_detection_epsilon") {
                try { 
                    config.shape_detection_epsilon = std::stod(value); 
                } catch (...) {
                    // 静默处理转换异常，保持默认值
                }
            }
            // 角点验证参数
            else if (key == "corner_check_enabled") {
                std::transform(value.begin(), value.end(), value.begin(), ::tolower);
                config.corner_check_enabled = (value == "true");
            } else if (key == "corner_check_distance") {
                try { config.corner_check_distance = std::stoi(value); } catch (...) {}
            }
            // 测距参数
            else if (key == "focal_length") {
                try { 
                    config.focal_length = std::stod(value); 
                } catch (...) {
                    // 静默处理转换异常，保持默认值
                }
            } else if (key == "object_real_width_cm") {
                try { 
                    config.object_real_width_cm = std::stod(value); 
                } catch (...) {
                    // 静默处理转换异常，保持默认值
                }
            } else if (key == "object_real_height_cm") {
                try { 
                    config.object_real_height_cm = std::stod(value); 
                } catch (...) {
                    // 静默处理转换异常，保持默认值
                }
            }
            // 调试参数
            else if (key == "ground_truth_distance_cm") {
                try {
                    config.ground_truth_distance_cm = std::stod(value);
                } catch (...) {
                    // 静默处理转换异常，保持默认值
                }
            }
            // 注意：未识别的键将被忽略
        }
    }

    std::cout << "配置文件 '" << filename << "' 加载成功。" << std::endl;
    return true;
}